package com.xspace.android.xafcommon.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;

public class CompressImage {

	public static Bitmap getSmallBitmap(String filePath, Activity context)
			throws Exception {
		int maxWidth = context.getWindowManager().getDefaultDisplay()
				.getWidth();
		int maxHeight = context.getWindowManager().getDefaultDisplay()
				.getHeight();
		byte[] photoByte = AppUtils.readStream(new FileInputStream(filePath));
		ByteArrayInputStream isBm = new ByteArrayInputStream(photoByte);
		BitmapFactory.Options newOpts = new BitmapFactory.Options();
		newOpts.inJustDecodeBounds = true;
		newOpts.inTempStorage = new byte[1024 * 1024 * 8];
		Bitmap photo = BitmapFactory.decodeStream(isBm, null, newOpts);
		int srcWidth = newOpts.outWidth;
		int srcHeight = newOpts.outHeight;
		int desWidth = 0;
		int desHeight = 0;
		double ratio = 0.0;
		if (srcWidth > srcHeight) {
			ratio = srcWidth / maxWidth;
			desWidth = maxWidth;
			desHeight = (int) (srcHeight / ratio);
		} else {
			ratio = srcHeight / maxHeight;
			desHeight = maxHeight;
			desWidth = (int) (srcWidth / ratio);
		}
		newOpts.inSampleSize = (int) (ratio) + 1;
		newOpts.inJustDecodeBounds = false;
		newOpts.outWidth = desWidth;
		newOpts.outHeight = desHeight;
		isBm = new ByteArrayInputStream(photoByte);
		photo = BitmapFactory.decodeStream(isBm, null, newOpts);
		int degree = readPictureDegree(filePath);
		if (degree > 0) {
			photo = rotateBitmap(photo, degree);
		}
		int quality = 90;// caculateQuality(newOpts.inTempStorage);
		if (photoByte.length <= 100 * 1024) {
			quality = 100;
		} else if (photoByte.length > 100 * 1024
				&& photoByte.length <= 500 * 1024) {
			quality = 80;
		} else if (photoByte.length > 500 * 1024
				&& photoByte.length <= 1024 * 1024) {
			quality = 60;
		} else {
			quality = 40;
		}
		ByteArrayOutputStream baos = null;
		try {
			baos = new ByteArrayOutputStream();
			photo.compress(Bitmap.CompressFormat.JPEG, quality, baos);
			photoByte = baos.toByteArray();

			FileOutputStream fos = new FileOutputStream(filePath);
			fos.write(photoByte);
			fos.flush();
			fos.close();
			newOpts.inTempStorage = new byte[0];
		} finally {
			try {
				isBm.close();
				if (baos != null)
					baos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return photo;

	}

	private static int caculateQuality(byte[] inTempStorage) {
		int length = Math.round(inTempStorage.length / 1024);
		if (length <= 100) {
			return 90;
		} else if (length <= 200) {
			return 80;
		} else if (length <= 300) {
			return 75;
		} else if (length <= 400) {
			return 70;
		} else if (length <= 500) {
			return 65;
		} else if (length <= 600) {
			return 60;
		} else if (length <= 700) {
			return 55;
		} else if (length <= 800) {
			return 50;
		} else if (length <= 900) {
			return 40;
		} else if (length <= 1000) {
			return 35;
		} else if (length <= 1024) {
			return 25;
		} else if (length <= 1024 * 2) {
			return 20;
		} else if (length <= 1024 * 3) {
			return 15;
		}
		return 10;
	}

	public static Bitmap getSmallBitmap(String filePath,
			ByteArrayOutputStream baos) {

		final BitmapFactory.Options options = new BitmapFactory.Options();
		setOptionsBeforeCompress(filePath, options);
		BitmapFactory.decodeFile(filePath, options);

		// Calculate inSampleSize
		options.inSampleSize = calculateInSampleSize(options, 480, 800);

		// Decode bitmap with inSampleSize set
		options.inJustDecodeBounds = false;
		options.inDensity = 480 * 800;
		Bitmap bm = BitmapFactory.decodeFile(filePath, options);
		if (bm == null) {
			return null;
		}
		int degree = readPictureDegree(filePath);
		if (degree != 0) {
			bm = rotateBitmap(bm, degree);
		}
		bm.compress(Bitmap.CompressFormat.JPEG,
				caculateQuality(options.inTempStorage), baos);

		return bm;

	}

	private static void setOptionsBeforeCompress(String filePath,
			final BitmapFactory.Options options) {
		options.inJustDecodeBounds = true;
		options.inTempStorage = new byte[getFileSize(filePath)];
	}

	private static int getFileSize(String path) {
		System.out.println((int) (new File(path).length()));
		return (int) (new File(path).length());
	}

	private static int calculateInSampleSize(BitmapFactory.Options options,
			int reqWidth, int reqHeight) {
		// Raw height and width of image
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;

		if (height > reqHeight || width > reqWidth) {
			final int heightRatio = Math.round((float) height
					/ (float) reqHeight);
			final int widthRatio = Math.round((float) width / (float) reqWidth);
			inSampleSize = heightRatio < widthRatio ? widthRatio : heightRatio;
		}
		System.out.println("-----------inSampleSize:" + inSampleSize);
		return inSampleSize;
	}

	private static Bitmap rotateBitmap(Bitmap bitmap, int rotate) {
		if (bitmap == null)
			return null;

		int w = bitmap.getWidth();
		int h = bitmap.getHeight();

		// Setting post rotate to 90
		Matrix mtx = new Matrix();
		mtx.postRotate(rotate);
		return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
	}

	private static int readPictureDegree(String path) {
		int degree = 0;
		try {
			ExifInterface exifInterface = new ExifInterface(path);
			int orientation = exifInterface.getAttributeInt(
					ExifInterface.TAG_ORIENTATION,
					ExifInterface.ORIENTATION_NORMAL);
			switch (orientation) {
			case ExifInterface.ORIENTATION_ROTATE_90:
				degree = 90;
				break;
			case ExifInterface.ORIENTATION_ROTATE_180:
				degree = 180;
				break;
			case ExifInterface.ORIENTATION_ROTATE_270:
				degree = 270;
				break;
			default:
				break;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return degree;
	}
}
